package com.wang.friend.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wang.friend.domain.exam.dto.ExamQueryDTO;
import com.wang.friend.domain.exam.dto.ExamRankDTO;
import com.wang.friend.domain.exam.vo.ExamRankVO;
import com.wang.friend.domain.exam.vo.ExamVO;
import com.wang.friend.domain.user.vo.UserVO;
import com.wang.friend.manager.ExamCacheManager;
import com.wang.friend.manager.UserCacheManager;
import com.wang.friend.mapper.exam.ExamMapper;
import com.wang.friend.mapper.user.UserExamMapper;
import com.wang.friend.service.IExamService;
import com.wang.common.core.domain.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ExamServiceImpl implements IExamService {

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ExamCacheManager examCacheManager;

    @Autowired
    private UserExamMapper userExamMapper;

    @Autowired
    private UserCacheManager userCacheManager;

    @Override
    public List<ExamVO> list(ExamQueryDTO examQueryDTO) {
        //开启分页查询
        PageHelper.startPage(examQueryDTO.getPageNum(), examQueryDTO.getPageSize());
        return examMapper.selectExamList(examQueryDTO);
        //注: C端用户只能查到已发布的竞赛
    }

    @Override
    public TableDataInfo redisList(ExamQueryDTO examQueryDTO) {

        //先从缓存中查出数据的大小
        Long total = examCacheManager.getListSize(examQueryDTO.getType(),null);

        List<ExamVO> examVOList;

        //如果缓存中没有数据,说明是第一次获取数据 --> 需要先从数据库中获取数据,再将其刷进缓存中
        if (total == null || total <= 0L) {
            //从库中查出数据
            examVOList = list(examQueryDTO);
            //把数据缓存进入redis
            examCacheManager.refreshCache(examQueryDTO.getType(),null);

            //更新total的值 (数据是从数据库中查到的,所以使用PageInfo)
            total = new PageInfo<>(examVOList).getTotal();
        } else {

            //从缓存中获取数据
            examVOList = examCacheManager.getExamVOList(examQueryDTO,null);

            //如果缓存中的数据有问题,需要更新缓存
            //这里之所以要再更新一次total,是因为Redis的数据可能有问题,在上一步的时候重新更新了
            total = examCacheManager.getListSize(examQueryDTO.getType(),null);
        }

        if (CollectionUtil.isEmpty(examVOList)){
            //如果最终查不到数据,则返回空
            return TableDataInfo.empty();
        }

        return TableDataInfo.success(examVOList,total);
    }

    @Override
    public String getFirstQuestion(Long examId) {
        //先检查缓存 (如果缓存中没数据则进行更新)
        checkAndRefresh(examId);
        return examCacheManager.getFirstQuestionId(examId).toString();
    }

    @Override
    public String preQuestion(Long examId,Long questionId) {
        //先检查缓存 (如果缓存中没有数据则进行更新)
        checkAndRefresh(examId);
        //在缓存中找到index为当前题目前一个的题目id 并返回
        return examCacheManager.preQuestion(examId,questionId).toString();
    }

    @Override
    public String nextQuestion(Long examId, Long questionId) {
        //先检查缓存 (如果缓存中没有数据则进行更新)
        checkAndRefresh(examId);
        //在缓存中找到index为当前题目后一个的题目id 并返回
        return examCacheManager.nextQuestion(examId,questionId).toString();
    }

    @Override
    public TableDataInfo rankList(ExamRankDTO examRankDTO) {
        //1.先从缓存中获取排名列表的大小
        Long total = examCacheManager.getRankListSize(examRankDTO.getExamId());

        List<ExamRankVO> examRankVOList;

        //2.判断缓存中是否存在信息,如果不存在,需要从数据库中同步
        if (total == null || total <= 0){
            //从数据库同步信息
            PageHelper.startPage(examRankDTO.getPageNum(),examRankDTO.getPageSize());
            examRankVOList = userExamMapper.selectExamRankList(examRankDTO.getExamId());
            //刷新缓存
            examCacheManager.refreshExamRankCache(examRankDTO.getExamId());
            //更新total的值
            total = new PageInfo<>(examRankVOList).getTotal();
        } else {
            //如果缓存中存在数据,直接获取
            examRankVOList = examCacheManager.getExamRankList(examRankDTO);
        }

        if (CollectionUtil.isEmpty(examRankVOList)){
            //如果获取到的结果为空
            return TableDataInfo.empty();
        }
        //转换结果
        assembleExamRankVOList(examRankVOList);
        return TableDataInfo.success(examRankVOList,total);
    }


    /**
     * 检查数据在缓存中是否存在,如果存在就返回,如果不存在则刷新
     * @param examId 竞赛id
     */
    private void checkAndRefresh(Long examId){
        //查询缓存中列表的大小
        Long size = examCacheManager.getExamQuestionListSize(examId);
        //如果列表大小不合法,则刷新缓存
        if (size == null || size <= 0){
            examCacheManager.refreshExamQuestionCache(examId);
        }
        //如果列表不为空,不做任何操作
    }

    private void assembleExamRankVOList(List<ExamRankVO> examRankVOList){
        if (CollectionUtil.isEmpty(examRankVOList)){
            return;
        }
        //根据用户id把用户昵称补全
        for (ExamRankVO examRankVO : examRankVOList){
            Long userId = examRankVO.getUserId();
            //从缓存中获取用户信息
            UserVO userVO = userCacheManager.getUserById(userId);
            examRankVO.setNickName(userVO.getNickName());
        }
    }
}
